﻿package bdz.common.display{
	import fl.motion.Tweenables;
	import flash.display.Sprite;
	import flash.display.MovieClip;
	import flash.events.*;
	import flash.text.TextField;
	import flash.geom.Rectangle;
	import fl.transitions.easing.*;
	import fl.transitions.Tween;
	import fl.transitions.TweenEvent;
	
	import bdz.common.events.SliderEvent;
	import bdz.common.utils.BitmapUtils;
	
	public class Slider extends MovieClip{
		protected var upbutton:MovieClip;
		protected var downbutton:MovieClip;
		protected var thumb:MovieClip;
		protected var prog:MovieClip;
		protected var track:MovieClip;
		private var enterFramer:Sprite;
		private var _orientation:String = "vertical";
		private var _resizethumb:Boolean = false;
		protected var pos:String;
		protected var prop:String;
		protected var mouseprop:String;
		protected var scaleprop:String;
		
		
		private var _scrollable:Number;
		private var _steps:Number;
		
		private var _tweened:Boolean = true;
		private var _ease;
		private var _tspeed;
		private var tt:Tween;
		
		protected var _maxscroll:Number;
		
		protected var baseline:MovieClip;
		
		protected var svalue:Number = 0;
		protected var pct:Number = 0;
		protected var osvalue:Number = 0;
		
		protected var _manualSteps:Number;
		function Slider() {
			baseline = new MovieClip();
			addChild(baseline);
			var nheight:Number = height;
			var nwidth:Number = width;
			scaleX = scaleY = 1;
			BitmapUtils.createBounds(baseline, nwidth, nheight, 1);
			baseline.alpha = 0;
			setProps();
		}
		private function setProps():void{
			
			if (_orientation == "vertical") {
				mouseprop = "mouseY";
				scaleprop = "scaleY";
				pos = "y";
				prop = "height";
				
				var temph = height
				height = baseline.height
				baseline.height = temph;
				
			} else {
				
				mouseprop = "mouseX";
				scaleprop = "scaleX";
				pos = "x";
				prop = "width";
				
				var tempw = width
				width = baseline.width
				baseline.width = tempw;
				
			}
			baseline.alpha = 0;
			
		}
		protected function attachElements() {
			if (upbutton && !contains(upbutton)) {
				upbutton[pos] = 0;
				upbutton.mouseChildren = false;
				upbutton.buttonMode = true;
				upbutton.addEventListener(MouseEvent.MOUSE_DOWN, checkButtonPress);
				upbutton.addEventListener(MouseEvent.MOUSE_UP, checkButtonPress);
				addChild(upbutton);
			}
			if (downbutton && !contains(downbutton)) {
				downbutton[pos] = baseline[prop]-downbutton[prop];
				downbutton.mouseChildren = false;
				downbutton.buttonMode = true;
				downbutton.addEventListener(MouseEvent.MOUSE_UP, checkButtonPress);
				downbutton.addEventListener(MouseEvent.MOUSE_DOWN, checkButtonPress);
				addChild(downbutton);
			}
			if (track && !contains(track)) {
				try {
					track[pos] = upbutton[pos]+upbutton[prop];
				} catch (e:Error) {
					track[pos] = 0;
				}
				track.addEventListener(MouseEvent.CLICK, trackClicked);
				addChild(track);
			}
			
			if (prog){
				 if(!contains(prog)) {
					try {
						prog[pos] = track[pos];
					} catch (e:Error) {
					}
					prog.addEventListener(MouseEvent.CLICK, trackClicked);
					addChild(prog);
				} else if(!contains(prog)){
					prog = new MovieClip();
					prog[pos] = track[pos];
					BitmapUtils.createBounds(prog, track.width, track.height, 0);
					addChild(prog);
				}
			}
			
			try {
				track[prop] = baseline[prop] - (downbutton[prop]+upbutton[prop]);
			} catch (e:Error) {
				track[prop] = baseline[prop];
			}
			try {
				prog[prop] = 0;
			} catch (e:Error) {
			}
			
			if (thumb && !contains(thumb)) {
				thumb[pos] =  track[pos];
				thumb.addEventListener(MouseEvent.MOUSE_DOWN, thumbClick);
				thumb.addEventListener(MouseEvent.MOUSE_UP, thumbReleased);
				addChild(thumb);
			}
		}
		private function trackClicked(evt:MouseEvent):void{
			var mprop:Number = this[mouseprop];
			if(mprop+thumb[prop]>track[prop]){
				mprop = track[prop]-thumb[prop];
			}
			var thumbTween:Tween = new Tween(thumb, pos, Strong.easeOut, thumb[pos], mprop, .8, true);
			thumbTween.addEventListener(TweenEvent.MOTION_CHANGE, scrollMovement)
		}
		protected function scrollMovement(evt:* = null):void {
			var diff:Number = thumb[pos]-track[pos];
			var totalsteps = (diff)*_steps;
			var val = 0;
			try {
				prog[prop] = diff;
			} catch (e:Error) {
			}
			pct = Math.ceil((((thumb[pos]-track[pos])/_scrollable)*100));	
			svalue = Math.ceil(_maxscroll*(pct*.01));
			dispatchEvent(new SliderEvent(SliderEvent.SCROLL, {percent:pct, value:svalue}));
		}
		private function skipScrollTo(n:Number, dispatch:Boolean = true):void{
			if(n == 0){
				try{
					var thumbTween:Tween = new Tween(thumb, pos, Strong.easeOut, thumb[pos], 0, .8, true);
					if(dispatch){
						thumbTween.addEventListener(TweenEvent.MOTION_CHANGE, scrollMovement)
					}else{
						var tt:Tween = new Tween(prog, prop, Strong.easeOut, prog[prop], 0, .8, true);
					}
				}catch(e:Error){
					
				}
				return;
			}
			try{
				var pct = Math.ceil((n/_maxscroll || _scrollable)*100);
				thumbTween = new Tween(thumb, pos, Strong.easeOut, thumb[pos], _scrollable*(pct*.01), .8, true);
				if(dispatch){
					thumbTween.addEventListener(TweenEvent.MOTION_CHANGE, scrollMovement)
					scrollMovement();
				}else{
					tt = new Tween(prog, pos, Strong.easeOut, prog[prop], _scrollable*(pct*.01), .8, true);
				}
			}catch(e:Error){
				
			}
			
		}
		private function buttonPress(evt:Event):void{
			try{
				if(downbutton.pressed){
					scrollDown();
				}
			}catch(e:Error){
				
			}
			try{
				if(upbutton.pressed){
					scrollUp();
				}
			}catch(e:Error){
				
			}
		}
		private function checkButtonPress(evt:MouseEvent):void{
			if(evt.type == MouseEvent.MOUSE_DOWN){
				evt.currentTarget.pressed = true;
				evt.currentTarget.addEventListener(Event.ENTER_FRAME, buttonPress);
			}else{
				evt.currentTarget.pressed = false;
				evt.currentTarget.removeEventListener(Event.ENTER_FRAME, buttonPress);
			}
		}
		private function thumbReleased(evt:MouseEvent):void {
			stage.removeEventListener(MouseEvent.MOUSE_UP, thumbReleased);
			stage.removeEventListener(Event.ENTER_FRAME, scrollMovement);
			thumb.stopDrag();
		}
		private function thumbClick(evt:MouseEvent):void {
			stage.addEventListener(MouseEvent.MOUSE_UP, thumbReleased);
			if (_orientation == "vertical") {
				thumb.startDrag(false, new Rectangle(track.x, track.y, track.x,track.height-thumb.height));
			} else {
				thumb.startDrag(false, new Rectangle(track.x, track.y, track.width-thumb.width,track.x));
			}
			stage.addEventListener(Event.ENTER_FRAME, scrollMovement);

		}
		
		protected function scrollUp(evt:* = null):void {
			if (thumb[pos]>track[pos]) {
				thumb[pos] -= _manualSteps || _steps;
				if (thumb[pos] < track[pos]) {
					thumb[pos] = track[pos];
				}
				scrollMovement();
			}
		}
		protected function scrollDown(evt:* = null):void {
			if (thumb[pos]+thumb[prop]<(track[pos]+track[prop])) {
				thumb[pos] += _manualSteps || _steps;
				if (thumb[pos]+thumb[prop] > track[pos]+track[prop]) {
					thumb[pos] = (track[pos]+track[prop]) - thumb[prop];
				}
				scrollMovement();
			}
		}
		private function computeScrollValues() {
			attachElements();
			_scrollable = (track[prop]+track[pos]-thumb[prop]);
			try {
				_scrollable -= downbutton[prop];
			} catch (e:Error) {
			}
			
			_steps = _maxscroll/_scrollable;
			
			if(_resizethumb){
				//resize thumb by percent
				
				
				//recompute after resizing thumb
				
				_scrollable = (track[prop]+track[pos]-thumb[prop]);
				_steps = _maxscroll/_scrollable;
			}
			
		}
		public function setManualMouseWheel(evt:MouseEvent):void{
			onTargetMouseWheel(evt);
		}
		private function onTargetMouseWheel(evt:MouseEvent):void {
			if (evt.delta>0) {
				scrollUp();
			} else {
				scrollDown();
			}
		}
		public function reset():void{
			skipScrollTo(0, false);
		}
		public function scrollToMax():void{
			thumb[pos] = (track[pos]+track[prop]) - thumb[prop];
			scrollMovement();
		}
		public function set scrollTo(s:Number):void{
			skipScrollTo(s);
		}
		public function set progressClip(p:MovieClip):void {
			prog = p;
		}
		public function get progressClip():MovieClip{
			return prog;
		}
		public function set trackClip(t:MovieClip):void {
			track = t;
		}
		public function set upButton(b:MovieClip):void {
			upbutton = b;
			
		}
		public function set downButton(b:MovieClip):void {
			downbutton = b;
		}
		public function set thumbButton(t:MovieClip):void {
			thumb = t;
		}
		public function set maxScroll(n:Number) {
			_maxscroll = n;
			thumb[pos] = track[pos];
			computeScrollValues();
		}
		public function set manualSteps(n:Number):void{
			_manualSteps = n;
		}
		public function get manualSteps():Number{
			return _manualSteps;
		}
		public function set scrollOrientation(o:String){
			_orientation = o;
			setProps();
		}
		public function set resizeThumb(b:Boolean):void{
			_resizethumb = b;
		}
		public function get resizeThumb():Boolean{
			return _resizethumb;
		}
		public function get virtualProp():Number{
			try {
				var tmp:Number =  baseline[prop] - (downbutton[prop]+upbutton[prop]);
			} catch (e:Error) {
				tmp = baseline[prop];
			}
			trace(tmp);
			return tmp;
		}
	}
}